package com.rightsidetech.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rightsidetech.commom.base.DelReq;
import com.rightsidetech.commom.base.ResponseData;
import com.rightsidetech.commom.enums.CodeIdEnum;
import com.rightsidetech.commom.utils.BeanValidator;
import com.rightsidetech.mall.dto.request.*;
import com.rightsidetech.mall.dto.response.BaesInfoDetailResp;
import com.rightsidetech.mall.dto.response.BaseInfoPageResp;
import com.rightsidetech.mall.dto.response.OptBaseInfoPageResp;
import com.rightsidetech.mall.entity.*;
import com.rightsidetech.mall.mapper.*;
import com.rightsidetech.mall.service.MallBaseInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import java.util.*;
import java.util.stream.Collectors;

@Service("mallBaseInfoService")
public class MallBaseInfoServiceImpl implements MallBaseInfoService {

    @Resource
    private MallBaseInfoMapper mallBaseInfoMapper;
    @Resource
    private MallGiftCommodityMapper mallGiftCommodityMapper;
    @Resource
    private MallTypeMapper mallTypeMapper;
    @Resource
    private MallIntegralCommodityMapper mallIntegralCommodityMapper;
    @Resource
    private MallBrandMapper mallBrandMapper;

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @Override
    public ResponseData save(BaseInfoReq req, String createrName, Long createrId) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        Long count = mallBaseInfoMapper.selectCountByName(req.getCommodityName());
        if (count > 0) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"商品名称已经存在");
        }
        MallType mallType = mallTypeMapper.selectByPrimaryKey(req.getTypeId());
        if(ObjectUtil.isEmpty(mallType)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"分类不存在");
        }
        MallBrand brand = mallBrandMapper.selectByPrimaryKey(req.getBrandId());
        if(ObjectUtil.isEmpty(brand)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"品牌不存在");
        }
        if (CollUtil.isNotEmpty(req.getSpecsList())) {
            if (CollUtil.isEmpty(req.getDetailSpecsList())) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"存在规格的商品,规格详情不允许为空");
            }
            //商品存在规格
            return saveDetail(req, createrName, createrId);
        }
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            MallBaseInfoWithBLOBs info = getMallBaseInfo(req, createrName, createrId);
            if (mallBaseInfoMapper.insertSelective(info) <= 0) {
                dataSourceTransactionManager.rollback(transaction);
                return ResponseData.fail("新增失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            dataSourceTransactionManager.rollback(transaction);
            return ResponseData.fail("添加失败");
        }
        dataSourceTransactionManager.commit(transaction);
        return ResponseData.success(CodeIdEnum.Success);
    }

    private MallBaseInfoWithBLOBs getMallBaseInfo(BaseInfoReq req, String createrName, Long createrId) {
        MallBaseInfoWithBLOBs info = new MallBaseInfoWithBLOBs();
        info.setBrandId(req.getBrandId());
        info.setCode(getCode());
        info.setCommodityName(req.getCommodityName());
        info.setTypeId(req.getTypeId());
        info.setCreatedAt(new Date());
        info.setCreaterId(createrId);
        info.setCreaterName(createrName);
        info.setIsDeleted((byte) 0);
        return info;
    }

    private ResponseData saveDetail(BaseInfoReq req, String createrName, Long createrId) {
        List<CommoditySpecsReq> specsList = req.getSpecsList();
        List<DetailSpecsReq> detailSpecsList = req.getDetailSpecsList();
        ResponseData check = checkSpecs(specsList, detailSpecsList);
        if (ObjectUtil.isNotEmpty(check)) {
            return check;
        }
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);
        try {
            MallBaseInfoWithBLOBs info = getMallBaseInfo(req, createrName, createrId);
            info.setSpecsJson(JSONUtil.toJsonStr(specsList));
            info.setSpecsDetailJson(JSONUtil.toJsonStr(detailSpecsList));
            if (mallBaseInfoMapper.insertSelective(info) <= 0) {
                dataSourceTransactionManager.rollback(transaction);
                return ResponseData.fail("新增失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            dataSourceTransactionManager.rollback(transaction);
            return ResponseData.fail("添加失败");
        }
        dataSourceTransactionManager.commit(transaction);
        return ResponseData.success(CodeIdEnum.Success);
    }

    private ResponseData checkSpecs(List<CommoditySpecsReq> specsList, List<DetailSpecsReq> detailSpecsList) {
        Set<Long> idSet = specsList.stream().map(CommoditySpecsReq::getId).collect(Collectors.toSet());
        if (idSet.size() < specsList.size()) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格名id不可重复");
        }
        Set<String> nameSet = specsList.stream().map(CommoditySpecsReq::getSpecsName).collect(Collectors.toSet());
        if (nameSet.size() < specsList.size()) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格名不可重复");
        }
        for (CommoditySpecsReq specs : specsList) {
            ConstraintViolation validate = BeanValidator.validate(specs);
            if (validate != null) {
                return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
            }
            List<CommoditySpecsValueReq> valueList = specs.getValueList();
            for (CommoditySpecsValueReq valueReq : valueList) {
                ConstraintViolation validate1 = BeanValidator.validate(valueReq);
                if (validate1 != null) {
                    return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate1.getMessage());
                }
            }
            Set<Long> valueIdSet = valueList.stream().map(CommoditySpecsValueReq::getId).collect(Collectors.toSet());
            if (valueIdSet.size() < valueList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格值id不可重复");
            }
            Set<String> valueSet = valueList.stream().map(CommoditySpecsValueReq::getSpecsValue).collect(Collectors.toSet());
            if (valueSet.size() < valueList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格值不可重复");
            }
        }
        Set<String> codeSet = detailSpecsList.stream().map(DetailSpecsReq::getCode).collect(Collectors.toSet());
        if (codeSet.size() < detailSpecsList.size()) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格条码不可重复");
        }
        for (String code : codeSet) {
            try {
                Integer.parseInt(code);
            } catch (Exception e) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格条码必须为数字");
            }
        }
        for (DetailSpecsReq detail : detailSpecsList) {
            ConstraintViolation validate = BeanValidator.validate(detail);
            if (validate != null) {
                return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
            }
            List<DetailSpecsNameReq> nameList = detail.getNameList();
            List<DetailSpecsValueReq> valueList = detail.getValueList();
            if (nameList.size() != valueList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格明细规格名和规格值数量不一致");
            }
            for (int i = 0; i < nameList.size(); i++) {
                DetailSpecsNameReq detailSpecsNameReq = nameList.get(i);
                DetailSpecsValueReq valueReq = valueList.get(i);
                ConstraintViolation validate1 = BeanValidator.validate(detailSpecsNameReq);
                if (validate1 != null) {
                    return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate1.getMessage());
                }
                ConstraintViolation validate2 = BeanValidator.validate(valueReq);
                if (validate2 != null) {
                    return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate2.getMessage());
                }
            }
            Set<Long> nameIdSet = nameList.stream().map(DetailSpecsNameReq::getId).collect(Collectors.toSet());
            if (nameIdSet.size() < nameList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格明细规格名id重复");
            }
            Set<String> specsNameSet = nameList.stream().map(DetailSpecsNameReq::getSpecsName).collect(Collectors.toSet());
            if (specsNameSet.size() < nameList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格明细规格名重复");
            }
            Set<Long> valueIdSet = valueList.stream().map(DetailSpecsValueReq::getId).collect(Collectors.toSet());
            if (valueIdSet.size() < valueList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格明细规格值id重复");
            }
            Set<String> specsValueSet = valueList.stream().map(DetailSpecsValueReq::getSpecsValue).collect(Collectors.toSet());
            if (specsValueSet.size() < valueList.size()) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"规格明细规格值重复");
            }
        }
        return null;
    }

    private String getCode() {
        String code = RandomUtil.randomNumbers(15);
        Long count = mallBaseInfoMapper.selectCountByCode(code);
        if (count > 0) {
            return getCode();
        }
        return code;
    }

    @Override
    public ResponseData<PageInfo<BaseInfoPageResp>> page(BaseInfoPageReq req) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BaseInfoPageResp> result = mallBaseInfoMapper.selectPageList(req);
        return ResponseData.success(new PageInfo<>(result));
    }

    @Override
    public ResponseData<BaesInfoDetailResp> getBaesDetail(Long id) {
        if (null == id || id < 0) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"id不可为空,不可小于0");
        }
        BaesInfoDetailResp result = mallBaseInfoMapper.selectInfoDetailById(id);
        if (ObjectUtil.isEmpty(result)) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到该商品");
        }
        MallType mallType = mallTypeMapper.selectByPrimaryKey(result.getTypeId());
        List<Long> typeIds = new ArrayList<>();
        typeIds.add(result.getTypeId());
        if(ObjectUtil.isNotEmpty(mallType)){
            String typeName = mallType.getTypeName();
            while (mallType.getParentId() != 0){
                MallType type = mallTypeMapper.selectByPrimaryKey(mallType.getParentId());
                typeIds.add(type.getId());
                typeName = type.getTypeName() + "/" + typeName;
                mallType = type;
            }
            result.setTypeName(typeName);
        }
        if (StrUtil.isNotEmpty(result.getSpecsJson())) {
            result.setSpecsList(JSONUtil.toList(result.getSpecsJson(), CommoditySpecsReq.class));
        }
        if (StrUtil.isNotEmpty(result.getSpecsDetailJson())) {
            result.setDetailSpecsList(JSONUtil.toList(result.getSpecsDetailJson(), DetailSpecsReq.class));
        }
        result.setTypeIds(typeIds);
        return ResponseData.success(result);
    }

    @Override
    public ResponseData update(BaseInfoUpReq req, String updaterName, Long updaterId) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        MallType mallType = mallTypeMapper.selectByPrimaryKey(req.getTypeId());
        if(ObjectUtil.isEmpty(mallType)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"分类不存在");
        }
        MallBrand brand = mallBrandMapper.selectByPrimaryKey(req.getBrandId());
        if(ObjectUtil.isEmpty(brand)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"品牌不存在");
        }
        MallBaseInfoWithBLOBs baseInfo = mallBaseInfoMapper.selectByPrimaryKey(req.getId());
        if (ObjectUtil.isEmpty(baseInfo) || baseInfo.getIsDeleted() == 1) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到要更新的数据");
        }
        if (!req.getCommodityName().equals(baseInfo.getCommodityName())) {
            Long count = mallBaseInfoMapper.selectCountByName(req.getCommodityName());
            if (count > 0) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"商品名称已经存在");
            }
        }
        baseInfo.setCommodityName(req.getCommodityName());
        baseInfo.setBrandId(req.getBrandId());
        baseInfo.setCode(getCode());
        baseInfo.setTypeId(req.getTypeId());
        baseInfo.setUpdatedAt(new Date());
        baseInfo.setUpdaterId(updaterId);
        baseInfo.setUpdaterName(updaterName);
        if (CollUtil.isNotEmpty(req.getSpecsList())) {
            if (CollUtil.isEmpty(req.getDetailSpecsList())) {
                return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"存在规格的商品规格详情不允许为空");
            }
            ResponseData data = checkSpecs(req.getSpecsList(), req.getDetailSpecsList());
            if (ObjectUtil.isNotEmpty(data)) {
                return data;
            }
            baseInfo.setSpecsJson(JSONUtil.toJsonStr(req.getSpecsList()));
            baseInfo.setSpecsDetailJson(JSONUtil.toJsonStr(req.getDetailSpecsList()));
            if (mallBaseInfoMapper.updateByPrimaryKeyWithBLOBs(baseInfo) <= 0) {
                return ResponseData.fail("更新失败");
            }
            return ResponseData.success(CodeIdEnum.Success);
        }
        baseInfo.setSpecsJson(null);
        baseInfo.setSpecsDetailJson(null);
        if (mallBaseInfoMapper.updateByPrimaryKeyWithBLOBs(baseInfo) <= 0) {
            return ResponseData.fail("更新失败");
        }
        return ResponseData.success(CodeIdEnum.Success);
    }

    @Override
    public ResponseData isDelete(DelReq req) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        MallBaseInfoWithBLOBs info = mallBaseInfoMapper.selectByPrimaryKey(req.getId());
        if (ObjectUtil.isEmpty(info) || info.getIsDeleted() == 1) {
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(),"未找到要删除的数据");
        }
        if(info.getIsMaintain() == 1){
            return ResponseData.fail("此基础商品已经维护过商城商品不可删除");
        }
        info = new MallBaseInfoWithBLOBs();
        info.setId(req.getId());
        info.setIsDeleted((byte) 1);
        if (mallBaseInfoMapper.updateByPrimaryKeySelective(info) <= 0) {
            return ResponseData.fail("删除失败");
        }
        return ResponseData.success(CodeIdEnum.Success);
    }

    @Override
    public ResponseData<PageInfo<OptBaseInfoPageResp>> optBaseInfo(OptBaseInfoReq req) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<OptBaseInfoPageResp> result = mallBaseInfoMapper.selectOptPageList(req);
        return ResponseData.success(new PageInfo<>(result));
    }

    @Override
    public ResponseData<PageInfo<OptBaseInfoPageResp>> optIntegral(OptBaseInfoReq req) {
        ConstraintViolation validate = BeanValidator.validate(req);
        if (validate != null) {
            return new ResponseData<>(CodeIdEnum.ParameterMalformed.getValue(), validate.getMessage());
        }
        PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<OptBaseInfoPageResp> result = mallBaseInfoMapper.selectOptPageIntegral(req);
        return ResponseData.success(new PageInfo<>(result));
    }

    @Override
    public ResponseData<List<DetailSpecsReq>> createSpecs(Long id) {
        if(ObjectUtil.isEmpty(id)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(), "id不可为空");
        }
//        MallBaseInfoWithBLOBs info = mallBaseInfoMapper.selectByPrimaryKey(id);
//        if(ObjectUtil.isEmpty(info)){
//            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(), "没有找到基础商品");
//        }
//        String specsDetailJson = info.getSpecsDetailJson();
//        if(StrUtil.isBlank(specsDetailJson)){
//            return ResponseData.success();
//        }
//        List<String> list = new ArrayList<>();
//        list.add(specsDetailJson);

//        Map<String, Object> map = getMap(info);
        List<String> str = mallIntegralCommodityMapper.selectByBaseInfoId(id);
//        if(CollUtil.isEmpty(str)){
//            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(), "找不到规格");
//        }
        return specs(str);
    }

    @Override
    public ResponseData<List<DetailSpecsReq>> createSpecsGift(Long id) {
        if(ObjectUtil.isEmpty(id) || id <= 0){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(), "id不可为空，不可小于1");
        }
        MallBaseInfoWithBLOBs info = mallBaseInfoMapper.selectByPrimaryKey(id);
        if(ObjectUtil.isEmpty(info)){
            return ResponseData.fail(CodeIdEnum.ParameterMalformed.getValue(), "没有找到基础商品");
        }
        if(StrUtil.isBlank(info.getSpecsJson())){
            return ResponseData.success();
        }
        Map<String, Object> map = getMap(info);
        List<String> str = mallGiftCommodityMapper.selectByBaseInfoId(map);
        return specs(str);
    }

    private ResponseData<List<DetailSpecsReq>> specs(List<String> str){
        if(CollUtil.isEmpty(str)){
            return ResponseData.success();
        }
        List<DetailSpecsReq> result = new ArrayList<>();
        str.forEach(st -> result.add(JSONUtil.toBean(st,DetailSpecsReq.class)));
        return ResponseData.success(result);
    }

    private Map<String,Object> getMap(MallBaseInfoWithBLOBs info){
        List<DetailSpecsReq> specsReqList = JSONUtil.toList(info.getSpecsDetailJson(), DetailSpecsReq.class);
        List<String> list = new ArrayList<>();
        specsReqList.forEach(specs -> list.add(JSONUtil.toJsonStr(specs)));
        Map<String,Object> map = new HashMap<>();
        map.put("baseInfoId",info.getId());
        map.put("list",list);
        return map;
    }

    @Override
    public MallBaseInfo selectByPrimaryKey(Long id) {
        return mallBaseInfoMapper.selectByPrimaryKey(id);
    }
}
